/**
 * 函数节流（throttle）：当持续触发事件时，保证一定时间段内只调用一次事件处理函数。
 * @param {*} fn 执行的函数
 * @param {*} interval 间隔的时间
 * @return function
 */
export function throttle(fn, interval = 200) {
  let _self = fn; // 保存需要被延迟执行的函数引用
  let firstTime = true; // 是否初次调用
  let timer; // 定时器
  return function() {
    let args = arguments;
    let _me = this;
    if (firstTime) {
      // 如果是第一次调用不需要延迟执行
      _self.call(_me, args);
    }
    if (timer) {
      // 如果定时器还在，说明前一次延迟执行还没有完成
      return false;
    }
    timer = setTimeout(() => {
      // 延迟一段时间执行
      clearTimeout(timer); // 清除定时器 避免下一次return false
      timer = null;
      _self.call(_me, args);
    }, interval);
  };
}

/**
 * 函数防抖（debounce）：当持续触发事件时，一定时间段内没有再触发事件，事件处理函数才会执行一次，如果设定的时间到来之前，又一次触发了事件，就重新开始延时。
 * @param {*} fn 执行的函数
 * @param {*} interval 间隔的时间
 * @return function
 */
export function debounce(fn, interval = 200) {
  let timer;
  let _self = fn;
  return function() {
    clearTimeout(timer);
    let args = arguments; // fn所需要的参数
    let _me = this; // 当前的this
    timer = setTimeout(() => {
      _self.call(_me, args);
    }, interval);
  };
}
/**
 * 深拷贝（deepClone）
 * @param {*} obj 拷贝的对象
 * @param {*} hash
 */
export function deepClone(obj, hash = new WeakMap()) {
  // 如果是 null 或者 undefined 我就不进行拷贝操作了
  if (obj === null) return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  // obj 可能是对象或者普通值，如果只是个函数的话，也不进行拷贝
  if (typeof obj !== "object") return obj;
  // 是对象的话就要进行拷贝了
  if (hash.get(obj)) return hash.get(obj);
  // 找到的是所属类原型上的 constructor，而原型上的 construction 指向的是当前类的本身
  let cloneObj = new obj.constructor();
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      // 实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

/**
 * 判断是否是url
 * @param {*} s
 * @returns
 */
export function isUrl(s) {
  var regex = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/|Http:\/\/|Https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/;
  return regex.test(s);
}
